package com.health.trans.config;

import cn.hutool.core.collection.CollUtil;
import com.health.trans.common.entity.ApiResponse;
import com.health.trans.common.entity.CodeEnum;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolationException;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * @author qyh
 */
@RestControllerAdvice
@Slf4j
public class ApiControllerAdvice {


    private static final Logger logger = LoggerFactory.getLogger(ApiControllerAdvice.class);

    /**
     * 全局异常捕捉处理
     *
     * @param ex
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public ApiResponse<Object> errorHandler(Exception ex) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        ex.printStackTrace(pw);
        String content = sw.toString();
        logger.error(content, ex);
        return ApiResponse.response(CodeEnum.SYSTEM_ERROR.getCode(), analysisLog(content));
    }

    /**
     * 拦截捕捉自定义异常 MyException.class
     *
     * @param ex
     * @return
     */



    /**
     * @param ex
     * @return
     */
    @ExceptionHandler(BindException.class)
    public ApiResponse<Object> bindException(BindException ex) {
        //捕获的所有错误对象
        List<ObjectError> allErrors = ex.getAllErrors();
        StringBuilder builder = new StringBuilder();
        builder.append("[");
        for (int i = 0; i < allErrors.size(); i++) {
            if (i != allErrors.size() - 1) {
                builder.append(allErrors.get(i).getDefaultMessage() + ",");
            } else {
                builder.append(allErrors.get(i).getDefaultMessage());
            }
        }
        builder.append("]");
        printError(ex);
        return ApiResponse.response(CodeEnum.ERROR.getCode(), builder.toString());

    }

    private void printError(Exception ex) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        ex.printStackTrace(pw);
        String content = sw.toString();
        logger.error(content, ex);
    }

    /**
     * 处理请求对象属性不满足校验规则的异常信息
     *
     * @param exception
     * @return
     * @throws Exception
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public ApiResponse<Object> exception(MethodArgumentNotValidException exception) {
        BindingResult result = exception.getBindingResult();
        List<? extends ObjectError> fieldErrors = result.getFieldErrors();
        if (CollUtil.isEmpty(fieldErrors)) {
            fieldErrors = result.getAllErrors();
        }
        StringBuilder builder = new StringBuilder();
        for (ObjectError error : fieldErrors) {
            builder.append(error.getDefaultMessage() + "\n");
        }
        printError(exception);
        return ApiResponse.response(CodeEnum.ERROR.getCode(), builder.toString());
    }

    /**
     * 处理请求单个参数不满足校验规则的异常信息
     *
     * @param exception
     * @return
     * @throws Exception
     */
    @ExceptionHandler(value = ConstraintViolationException.class)
    public ApiResponse<Object> constraintViolationExceptionHandler(ConstraintViolationException exception) {
        printError(exception);
        return ApiResponse.response(CodeEnum.ERROR.getCode(), exception.getMessage());
    }


    private static String analysisLog(String content) {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8));
        String line;
        StringBuffer strbuf = new StringBuffer();
        try {
            while ((line = bufferedReader.readLine()) != null) {
                if (line.indexOf('\t') != 0) {
                    strbuf.append(line + "\r\n");
                }
            }
        } catch (IOException e) {
            logger.error("错误信息", e);
        }

        return strbuf.toString();

    }

}
